package modele.Batiment;


import java.io.Serializable;

import controleur.Controleur;

import modele.Joueur;
import modele.Position;

public abstract class Batiment implements Serializable{
	private static final long serialVersionUID = 6807566190653084054L;
	protected String nom;
	protected int pointsDeVie;
	protected int niveau;
	protected int coutConstructionOr;
	protected int coutConstructionElixir;
	protected int tempsConstruction;
	protected int longueurCote;
	protected Position position;//désigne la position du coin bas gauche du Batiment
	protected Joueur joueur;//joueur qui a construit le batiment
	
	public Batiment(String nom, int pointsDeVie, int niveau, int coutConstructionOr, int coutConstructionElixir, int tempsConstruction, int longueurCote, Position position, Joueur joueur) {
		assert pointsDeVie >= 0;
		assert niveau >= 0;
		assert coutConstructionOr >= 0;
		assert coutConstructionElixir >= 0;
		assert tempsConstruction >= 0;
		assert longueurCote > 0;
		
		this.nom = nom;
		this.pointsDeVie = pointsDeVie;
		this.niveau = niveau;
		this.coutConstructionOr = coutConstructionOr;
		this.coutConstructionElixir = coutConstructionElixir;
		this.tempsConstruction = tempsConstruction;
		this.longueurCote = longueurCote;
		this.position = position;
		this.joueur = joueur;
	}
	
	/**
	 * retourne la capacité de stockage d'or du bâtiment
	 * @return la capacité de stockage d'or
	 */
	public int getCapaciteStockageOr(){return 0;}
	
	/**
	 * retourne la quantité actuelle d'or du bâtiment
	 * @return quantité actuelle d'or
	 */
	public int getQuantiteActuelleOr(){return 0;}
	
	public int getProductionParSecondeOr(){return 0;}
	
	public int getProductionParSecondeElixir(){return 0;}
	
	
	/**
	 * retourne la capacité de stockage d'élixir du bâtiment
	 * @return la capacité de stockage d'élixir
	 */
	public int getCapaciteStockageElixir(){return 0;}
	
	/**
	 * retourne la quantité actuelle d'élixir du bâtiment
	 * @return quantité actuelle d'élixir
	 */
	public int getQuantiteActuelleElixir(){return 0;}
	
	/**
	 * détermine si le niveau d'un batiment est augmentable
	 * @param joueur joueur voulant augmenter le niveau de son batiment
	 * @return true si l'augmentation est possible, false sinon
	 */
	public boolean niveauAugmentable()
	{
		if(coutConstructionOr*niveau <= joueur.getRessourceOr() &&  coutConstructionElixir*niveau <= joueur.getRessourceElixir())
			return true;
		else
			return false;
	}
	
	
	/**
	 * si l'augmentation du niveau est possible :
	 * paye l'augmentation, augmente les points de vie de 10%, appelle l'augmentation spécifique aux sous-classes,
	 * et incrémente le niveau
	 * sinon la fonction ne fait rien
	 */
	public void augmenterNiveau() {
		if(niveauAugmentable())
		{
			joueur.setRessourceOr(joueur.getRessourceOr() - coutConstructionOr*niveau);
			joueur.setRessourceElixir(joueur.getRessourceElixir() - coutConstructionElixir*niveau);
			pointsDeVie = pointsDeVie+(pointsDeVie/10);
			augmenterNiveauSpecifique();
			niveau++;
		}
	}
	
	/**
	 * implante l'augmentation spécifique d'un niveau pour chaque classe fille
	 */
	protected abstract void augmenterNiveauSpecifique();
	
	/**
	 * la valeur de pointsDeVie doit être calculable à partir de niveau
	 * on choisit niveau*100 pour le moment
	 */
	public void reconstruire () {
		pointsDeVie = getPointsDeVieInitiaux();
		joueur.incrementerNbrBatimentsRestant();
	}
	
	abstract protected int getPointsDeVieInitiaux();

	public void recevoirDegats (int puissanceAttaque) {
		pointsDeVie = pointsDeVie - puissanceAttaque;

		if(pointsDeVie <= 0)
		{
			
			joueur.perdreBatiment(this);
		}
	}
	
	public String getNom(){
		return this.nom;
	}

	public int getPointsDeVie() {
		return pointsDeVie;
	}

	public void setPointsDeVie(int pointsDeVie) {
		this.pointsDeVie = pointsDeVie;
	}

	public int getNiveau() {
		return niveau;
	}

	public void setNiveau(int niveau) {
		this.niveau = niveau;
	}

	public int getCoutConstructionOr() {
		return coutConstructionOr;
	}

	public void setCoutConstructionOr(int coutConstructionOr) {
		this.coutConstructionOr = coutConstructionOr;
	}

	public int getCoutConstructionElixir() {
		return coutConstructionElixir;
	}

	public void setCoutConstructionElixir(int coutConstructionElixir) {
		this.coutConstructionElixir = coutConstructionElixir;
	}

	public int getTempsConstruction() {
		return tempsConstruction;
	}

	public void setTempsConstruction(int tempsConstruction) {
		this.tempsConstruction = tempsConstruction;
	}

	public int getLongueurCote() {
		return longueurCote;
	}

	public void setLongueurCote(int longueurCote) {
		this.longueurCote = longueurCote;
	}

	public Position getPosition() {
		return position;
	}

	public void setPosition(Position position) {
		this.position = position;
	}
	
	public void setJoueur(Joueur joueur)
	{
		this.joueur = joueur;
	}
	
	public void actionApresConstruction(Controleur controleur)
	{
		this.joueur = controleur.getJoueur();
		actionApresConstructionSpecifique(controleur);
	}
	
	abstract public void actionApresConstructionSpecifique(Controleur controleur);
	
	/**
	 * décrit l'état de l'instance
	 * @return une description de l'état de l'instance
	 */
	public String resumerEtat()
	{
		return new String("points de vie : "+pointsDeVie +'\n'+"niveau : "+ niveau+ "\n "+resumerEtatSpecifique());
	}
	
	abstract public String resumerEtatSpecifique();
	
}


